package net.fpeg.kotlin.play

fun main() {
//    字符串01("1011", 4).逻辑右移().let { println(it) }
//    字符串01("0110").plus(字符串01("1101"), 5).let { println(it) }
//    字符串01("0001").后n位(3).let { println(it) }
//    字符串01("0001")
//        .原码乘法一步(原码乘法迭代组合(字符串01("1000"), 字符串01("00001100"), 原码乘法操作类型.移位加B))
//        .let { println(it) }
    真值("1111").原码乘法演示(真值("1111")).let { println(it) }
}

data class 原码乘法迭代组合(
        val 乘数: 真值, val 被乘数: 真值, val 方法: 原码乘法操作类型, val 次数: Int = 0,
) {
    fun 原码乘法一步(): 原码乘法迭代组合 {
        val (乘数, 被乘数, 方法) = this
        return when (方法) {
            原码乘法操作类型.移位加B ->
                被乘数.run {
                    前n位(length() / 2)
                            .plus(乘数, 乘数.length() + 1)
                            .concat(后n位(length() / 2))
                }
            原码乘法操作类型.仅移位 -> 被乘数
            原码乘法操作类型.终止 -> {
                return 原码乘法迭代组合(乘数, 被乘数, 原码乘法操作类型.终止, 次数)
            }
        }.apply {
            if (次数 > 乘数.length() - 1) return 原码乘法迭代组合(乘数, 被乘数, 原码乘法操作类型.终止, 次数)
        }//保险
                .逻辑右移()
                .后n位(乘数.length() * 2)
                .let {
                    原码乘法迭代组合(
                            乘数, it, when {
                        乘数.length() == 次数 + 1 -> 原码乘法操作类型.终止
                        it.后n位(1).value == "1" -> 原码乘法操作类型.移位加B
                        else -> 原码乘法操作类型.仅移位
                    },
                            次数 + 1
                    )
                }
    }
}

data class 原码除法迭代组合(
        val 除数: 原码, val 被除数: 原码, val 方法: 原码除法操作类型, val 次数: Int = 0,
) {
    fun 除法一步(){
        when(方法){
            原码除法操作类型.恢复余数->return null
        }
        when(方法){
            原码除法操作类型.移位加B
        }
    }
}

data class 补码乘法迭代组合(
        val 乘数: 补码, val 负乘数: 补码, val 被乘数: 补码, val 方法: 补码乘法操作类型, val 终止步: Boolean, val 次数: Int = 0,
) {
    fun 补码乘法一步(): 补码乘法迭代组合 {
        val (乘数, 负乘数, 被乘数, 方法, 终止步) = this
        return when (方法) {
            补码乘法操作类型.移位加B -> 补码(
                    被乘数.前n位(乘数.length()).plus(乘数).concat(被乘数.后n位(乘数.length())).value
            )
            补码乘法操作类型.移位减B -> 补码(
                    被乘数.前n位(乘数.length()).plus(负乘数).concat(被乘数.后n位(乘数.length())).value
            )
            补码乘法操作类型.仅移位 -> 被乘数
            补码乘法操作类型.终止 -> return 补码乘法迭代组合(乘数, 负乘数, 被乘数, 方法, 终止步, 次数 + 1)
        }
                .apply {
                    if (终止步)
                        return 补码乘法迭代组合(
                                乘数, 负乘数, this, 补码乘法操作类型.终止, false, 次数 + 1)
                }
                .算数右移()
                .let {
                    补码乘法迭代组合(
                            乘数, 负乘数, it,
                            when (it.后n位(2).value) {
                                "00" -> 补码乘法操作类型.仅移位
                                "01" -> 补码乘法操作类型.移位加B
                                "10" -> 补码乘法操作类型.移位减B
                                "11" -> 补码乘法操作类型.仅移位
                                else -> throw Exception("asd")
                            },
                            次数 == 乘数.length() - 3,
                            次数 + 1
                    )
                }
    }
}

enum class 原码乘法操作类型 {
    移位加B, 仅移位, 终止
}

enum class 原码除法操作类型 {
    移位加B, 移位减B, 恢复余数, 终止
}

enum class 补码乘法操作类型 {
    移位加B, 移位减B, 仅移位, 终止
}

open class 真值(value: String = "00000000") {
    fun length() = value.length
    val value: String = when {
        Regex("^[01]{" + value.length + "}$").matches(value) -> value
        else -> throw Exception("aaaa")
    }


    fun 逻辑左移() = 真值(value.toCharArray().mapIndexed { index, _ ->
        when (index) {
            length() - 1 -> '0'
            else -> value[index + 1]
        }
    }.joinToString(""))


    fun toInt() = value.let { Integer.parseInt(it, 2) }

    fun plus(真值: 真值, length: Int = length()) =
            (toInt() + 真值.toInt())
                    .let { Integer.toBinaryString(it) }
                    .padStart(length, '0')
                    .let { 真值(it).后n位(length) }

    fun concat(真值: 真值) = 真值(value + 真值.value)

    fun 逻辑右移(): 真值 = 真值(
            value.toCharArray().mapIndexed { index, _ ->
                when (index) {
                    0 -> '0'
                    else -> value[index - 1]
                }
            }.joinToString("")
    )

    fun 反转() = 真值(value
            .replace('1', 'x')
            .replace('0', '1')
            .replace('x', '0')
    )

    fun 前n位(n: Int) = 真值(value.substring(0 until n))
    fun 后n位(n: Int) = 真值(value.substring(length() - n until length()))


    fun 原码乘法演示(被乘数: 真值): List<原码乘法迭代组合> {
        fun 内部操作(原码乘法迭代组合: 原码乘法迭代组合, 次数: Int): 原码乘法迭代组合 {
            var state = 原码乘法迭代组合.copy()
            for (x in 0..次数) state = state.原码乘法一步()
            return state
        }
        if (被乘数.length() != length()) throw java.lang.Exception("asd")
        return 原码乘法迭代组合(
                this, 真值("0".repeat(length())).concat(被乘数), when (被乘数.后n位(1).value) {
            "1" -> 原码乘法操作类型.移位加B
            else -> 原码乘法操作类型.仅移位
        }
        )
                .let { 原码乘法迭代组合 -> (0..3).map { 内部操作(原码乘法迭代组合, it) } }
    }

    override fun toString() = value
}

class 原码(value: String) : 真值(value = value) {
    fun sign() = when (前n位(1).value) {
        "1" -> -1
        else -> 1
    }

    fun 转补码() = 补码(when (sign()) {
        1 -> value
        0 -> value
        -1 -> 真值("1").concat(真值(value).后n位(length() - 1).反转()).plus(真值("1")).value
        else -> throw Exception("asd")
    })

    fun 除法演示(被除数: 原码) {

    }
}

class 补码(value: String) : 真值(value = value) {
    fun sign() = when (前n位(1).value) {
        "1" -> -1
        else -> 1
    }

    fun 取负数() = 反转().plus(真值("1")).value.let { 补码(it) }


    fun 算数左移() = 补码(逻辑左移().value)
    fun 算数右移() = 逻辑右移().let {
        when (sign()) {
            1 -> 补码(真值("0").concat(it.后n位(length() - 1)).value)
            0 -> 补码("0".repeat(length()))
            -1 -> 补码(真值("1").concat(it.后n位(length() - 1)).value)
            else -> throw Exception("asd")
        }
    }

    fun 补码乘法演示(被乘数: 补码): List<补码乘法迭代组合> {
        fun 内部操作(补码乘法迭代组合: 补码乘法迭代组合, 次数: Int): 补码乘法迭代组合 {
            var state = 补码乘法迭代组合.copy()
            for (x in 0..次数) state = state.补码乘法一步()
            return state
        }
        if (被乘数.length() != length()) throw java.lang.Exception("asd")
        val 加长被乘数 = 真值("0".repeat(length() + 1)).concat(被乘数).concat(真值("0")).value.let { 补码(it) }
        return 补码乘法迭代组合(
                this.前n位(1).concat(this).value.let { 补码(it) },
                this.取负数().run { 前n位(1).concat(this).value.let { 补码(it) } },
                加长被乘数,
                when (加长被乘数.后n位(2).value) {
                    "00" -> 补码乘法操作类型.仅移位
                    "01" -> 补码乘法操作类型.移位加B
                    "10" -> 补码乘法操作类型.移位减B
                    "11" -> 补码乘法操作类型.仅移位
                    else -> throw Exception("asd")
                },
                false
        )
                .let { 补码乘法迭代组合 -> (0 until length()).map { 内部操作(补码乘法迭代组合, it) } }
    }
}

//    fun 补码乘法演示(补码())


